#include "stdafx.h"
#include "EditObjectGui.h"

#include "Window.h"
#include "PushButton.h"
#include "OnOffButton.h"
#include "Label.h"
#include "Node.h"
#include "TextField.h"
#include "MyMath.h"
#include "Camera.h"
#include "Scene.h"

#include "GlobalAppData.h"

using namespace medit;

EditObjectGui::EditObjectGui(mscene::Scene & scene, const mscene::Camera & camera)
	: Window(Rect(mcore::GlobalAppData::Instance.ScreenWidth - 220, 50, 200, 500), "Edit object"),
	mScene(&scene), mCamera(&camera), NodeRemoved(false)
{
	mTextFieldName = new mgui::TextField(Rect(10, 30, 160, 20), mgui::TextField::TYPE_TEXT);
	mTextFieldName->addListener(mgui::TextField::EVENT_TEXT_CHANGED, std::bind(&EditObjectGui::textFieldNameChanged, this, std::placeholders::_1));
	addChild(*mTextFieldName);


	addChild(*new mgui::Label(Rect(10, 60, 160, 20), "Position"));

	mTextFieldPosX = new mgui::TextField(Rect(5, 85, 60, 20), mgui::TextField::TYPE_FLOAT);
	mTextFieldPosX->addListener(mgui::TextField::EVENT_TEXT_CHANGED, std::bind(&EditObjectGui::textFieldPositionChanged, this, std::placeholders::_1));
	addChild(*mTextFieldPosX);

	mTextFieldPosY = new mgui::TextField(Rect(70, 85, 60, 20), mgui::TextField::TYPE_FLOAT);
	mTextFieldPosY->addListener(mgui::TextField::EVENT_TEXT_CHANGED, std::bind(&EditObjectGui::textFieldPositionChanged, this, std::placeholders::_1));
	addChild(*mTextFieldPosY);

	mTextFieldPosZ = new mgui::TextField(Rect(135, 85, 60, 20), mgui::TextField::TYPE_FLOAT);
	mTextFieldPosZ->addListener(mgui::TextField::EVENT_TEXT_CHANGED, std::bind(&EditObjectGui::textFieldPositionChanged, this, std::placeholders::_1));
	addChild(*mTextFieldPosZ);


	addChild(*new mgui::Label(Rect(10, 110, 160, 20), "Rotation"));

	mTextFieldRotX = new mgui::TextField(Rect(5, 135, 60, 20), mgui::TextField::TYPE_FLOAT);
	mTextFieldRotX->addListener(mgui::TextField::EVENT_TEXT_CHANGED, std::bind(&EditObjectGui::textFieldRotationChanged, this, std::placeholders::_1));
	addChild(*mTextFieldRotX);

	mTextFieldRotY = new mgui::TextField(Rect(70, 135, 60, 20), mgui::TextField::TYPE_FLOAT);
	mTextFieldRotY->addListener(mgui::TextField::EVENT_TEXT_CHANGED, std::bind(&EditObjectGui::textFieldRotationChanged, this, std::placeholders::_1));
	addChild(*mTextFieldRotY);

	mTextFieldRotZ = new mgui::TextField(Rect(135, 135, 60, 20), mgui::TextField::TYPE_FLOAT);
	mTextFieldRotZ->addListener(mgui::TextField::EVENT_TEXT_CHANGED, std::bind(&EditObjectGui::textFieldRotationChanged, this, std::placeholders::_1));
	addChild(*mTextFieldRotZ);


	addChild(*new mgui::Label(Rect(10, 160, 160, 20), "Scale"));

	mTextFieldScaleX = new mgui::TextField(Rect(5, 185, 60, 20), mgui::TextField::TYPE_FLOAT);
	mTextFieldScaleX->addListener(mgui::TextField::EVENT_TEXT_CHANGED, std::bind(&EditObjectGui::textFieldScaleChanged, this, std::placeholders::_1));
	addChild(*mTextFieldScaleX);

	mTextFieldScaleY = new mgui::TextField(Rect(70, 185, 60, 20), mgui::TextField::TYPE_FLOAT);
	mTextFieldScaleY->addListener(mgui::TextField::EVENT_TEXT_CHANGED, std::bind(&EditObjectGui::textFieldScaleChanged, this, std::placeholders::_1));
	addChild(*mTextFieldScaleY);

	mTextFieldScaleZ = new mgui::TextField(Rect(135, 185, 60, 20), mgui::TextField::TYPE_FLOAT);
	mTextFieldScaleZ->addListener(mgui::TextField::EVENT_TEXT_CHANGED, std::bind(&EditObjectGui::textFieldScaleChanged, this, std::placeholders::_1));
	addChild(*mTextFieldScaleZ);


	mButtonIsStatic = new mgui::OnOffButton(Rect(5, 220, 80, 20), "Static", false);
	mButtonIsStatic->addListener(mgui::OnOffButton::EVENT_STATE_CHANGED, std::bind(&EditObjectGui::buttonIsStaticChanged, this, std::placeholders::_1));
	addChild(*mButtonIsStatic);



	mgui::OnOffButton * onOffButton = new mgui::OnOffButton(Rect(5, 260, 80, 20), "Move XZ", true);
	onOffButton->addListener(mgui::OnOffButton::EVENT_MOUSE_DRAGGED, std::bind(&EditObjectGui::buttonMoveXZMouseDragged, this, std::placeholders::_1));
	addChild(*onOffButton);

	onOffButton = new mgui::OnOffButton(Rect(90, 260, 80, 20), "Move Y", true);
	onOffButton->addListener(mgui::OnOffButton::EVENT_MOUSE_DRAGGED, std::bind(&EditObjectGui::buttonMoveYMouseDragged, this, std::placeholders::_1));
	addChild(*onOffButton);

	mgui::PushButton * pushButton = new mgui::PushButton(Rect(5, 290, 160, 20), "Copy object");
	pushButton->addListener(mgui::PushButton::EVENT_PUSHED, std::bind(&EditObjectGui::buttonCopy, this, std::placeholders::_1));
	addChild(*pushButton);

	pushButton = new mgui::PushButton(Rect(5, 320, 160, 20), "Delete object");
	pushButton->addListener(mgui::PushButton::EVENT_PUSHED, std::bind(&EditObjectGui::buttonDelete, this, std::placeholders::_1));
	addChild(*pushButton);

	//button = new mgui::OnOffButton(Rect(10, 60, 160, 20), "Show bounding geo");
	//button->addListener(mgui::OnOffButton::EVENT_STATE_CHANGED, std::bind(&RenderSettingsGui::buttonShowBoundingGeo, this, std::placeholders::_1));
	//GuiWindow->addChild(button);

	//button = new mgui::OnOffButton(Rect(10, 90, 160, 20), "Render SSAO");
	//button->addListener(mgui::OnOffButton::EVENT_STATE_CHANGED, std::bind(&RenderSettingsGui::buttonRenderSSAO, this, std::placeholders::_1));
	//GuiWindow->addChild(button);

	//button = new mgui::PushButton(Rect(10, 30, 160, 20), "Plane");
	//button->addListener(mgui::PushButton::EVENT_PUSHED,
	//	std::bind(&AddObjectGui::buttonPlaneClicked, this, std::placeholders::_1));
	//GuiWindow->addChild(button);

}

void EditObjectGui::setNode( mscene::Node & node )
{
	mNode = &node;

	mTextFieldName->setString(mNode->getName());
	updatePositionTextFields();
	updateRotationTextFields();
	updateScaleTextFields();
	mButtonIsStatic->Enabled = mNode->IsStatic;

	NodeRemoved = false;
}

void EditObjectGui::textFieldPositionChanged( const mgui::EventArgs & args )
{
	mNode->Position = XMFLOAT3(mTextFieldPosX->getFloat(), mTextFieldPosY->getFloat(), mTextFieldPosZ->getFloat());
	mNode->updateRigidBody();
}

void EditObjectGui::textFieldRotationChanged( const mgui::EventArgs & args )
{
	XMVECTOR orientation = XMQuaternionRotationRollPitchYaw(
		DEG_TO_RAD(mTextFieldRotX->getFloat()),
		DEG_TO_RAD(mTextFieldRotY->getFloat()),
		DEG_TO_RAD(mTextFieldRotZ->getFloat()));

	XMStoreFloat4(&mNode->Orientation, orientation);
	mNode->updateRigidBody();
}

void EditObjectGui::textFieldScaleChanged( const mgui::EventArgs & args )
{
	mNode->Scale = XMFLOAT3(mTextFieldScaleX->getFloat(), mTextFieldScaleY->getFloat(), mTextFieldScaleZ->getFloat());
	mNode->updateRigidBody();
}

void EditObjectGui::buttonIsStaticChanged( const mgui::EventArgs & args )
{
	mNode->IsStatic = ((const mgui::OnOffEventArgs*)&args)->On;
	//mNode->updateRigidBody();
}

void EditObjectGui::textFieldNameChanged( const mgui::EventArgs & args )
{
	mNode->setName(mTextFieldName->getText().c_str());
}

void EditObjectGui::buttonMoveXZMouseDragged( const mgui::EventArgs & args )
{
	float mouseChangeX = ((const mgui::MouseDragEventArgs*)&args)->MoveVector.x;
	float mouseChangeY = ((const mgui::MouseDragEventArgs*)&args)->MoveVector.y;

	XMVECTOR camLook = XMLoadFloat3(&mCamera->look());
	XMVECTOR camRight = XMLoadFloat3(&mCamera->right());
	camLook = XMVector3Normalize( XMVectorSetY( camLook, 0 ) );
	//camLook.m128_f32[0] *= -1;
	camRight = XMVector3Normalize( XMVectorSetY( camRight, 0 ) );

	XMVECTOR move = camLook * (-mouseChangeY) * 0.5f + camRight * mouseChangeX * 0.5f;

	mNode->Position.x += XMVectorGetX(move);
	mNode->Position.z += XMVectorGetZ(move);
	mNode->updateRigidBody();
	updatePositionTextFields();
}

void EditObjectGui::buttonMoveYMouseDragged( const mgui::EventArgs & args )
{
	mNode->Position.y -= ((const mgui::MouseDragEventArgs*)&args)->MoveVector.y * 0.5f;
	mNode->updateRigidBody();
	updatePositionTextFields();
}

void EditObjectGui::buttonCopy( const mgui::EventArgs & args )
{
	mScene->addNode(*mNode->copy());
}

void EditObjectGui::buttonDelete( const mgui::EventArgs & args )
{
	mScene->deleteNode(*mNode);
	NodeRemoved = true;
}

void EditObjectGui::updatePositionTextFields()
{
	mTextFieldPosX->setFloat(mNode->Position.x);
	mTextFieldPosY->setFloat(mNode->Position.y);
	mTextFieldPosZ->setFloat(mNode->Position.z);
}

void EditObjectGui::updateRotationTextFields()
{
	XMVECTOR eulerAngles = mmath::quaternionToEulerAngles(XMLoadFloat4(&mNode->Orientation));
	mTextFieldRotX->setFloat(RAD_TO_DEG(XMVectorGetX(eulerAngles)));
	mTextFieldRotY->setFloat(RAD_TO_DEG(XMVectorGetY(eulerAngles)));
	mTextFieldRotZ->setFloat(RAD_TO_DEG(XMVectorGetZ(eulerAngles)));
}

void EditObjectGui::updateScaleTextFields()
{
	mTextFieldScaleX->setFloat(mNode->Scale.x);
	mTextFieldScaleY->setFloat(mNode->Scale.y);
	mTextFieldScaleZ->setFloat(mNode->Scale.z);
}
